package com.evan.review.ipc;

import android.content.Intent;
import android.os.Bundle;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.evan.review.R;

import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

/**
 * 共享内存通信示例
 * 展示如何使用MemoryFile和共享内存进行IPC
 * 
 * 注意：部分API在Android 10+上已被限制访问，此示例仅作演示
 * 对于实际应用，推荐使用SharedMemory (Android 8.1+) 或 MemoryFileApi
 */
public class SharedMemoryActivity extends AppCompatActivity {
    private static final String TAG = "SharedMemoryActivity";
    private static final String EXTRA_FILE_DESCRIPTOR = "file_descriptor";
    private static final int BUFFER_SIZE = 1024;
    
    private TextView tvStatus;
    private TextView tvMemoryContent;
    private EditText etContent;
    private Button btnWriteMemory;
    private Button btnReadMemory;
    private Button btnLaunchRemote;
    
    // 共享内存对象
    private MemoryFile memoryFile;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shared_memory);
        
        // 初始化视图
        tvStatus = findViewById(R.id.tv_shared_memory_status);
        tvMemoryContent = findViewById(R.id.tv_memory_content);
        etContent = findViewById(R.id.et_memory_content);
        btnWriteMemory = findViewById(R.id.btn_write_memory);
        btnReadMemory = findViewById(R.id.btn_read_memory);
        btnLaunchRemote = findViewById(R.id.btn_launch_remote_process);
        
        updateProcessInfo();
        
        // 创建共享内存
        try {
            createSharedMemory();
            updateStatus("共享内存已创建，大小: " + BUFFER_SIZE + " 字节");
        } catch (IOException e) {
            Log.e(TAG, "创建共享内存错误: " + e.getMessage());
            updateStatus("创建共享内存失败: " + e.getMessage());
            btnWriteMemory.setEnabled(false);
            btnReadMemory.setEnabled(false);
            btnLaunchRemote.setEnabled(false);
        }
        
        // 写入共享内存
        btnWriteMemory.setOnClickListener(v -> {
            String content = etContent.getText().toString();
            if (content.isEmpty()) {
                content = "来自进程 " + Process.myPid() + " 的共享内存测试数据";
                etContent.setText(content);
            }
            writeToSharedMemory(content);
        });
        
        // 读取共享内存
        btnReadMemory.setOnClickListener(v -> {
            readFromSharedMemory();
        });
        
        // 启动远程进程
        btnLaunchRemote.setOnClickListener(v -> {
            launchRemoteProcess();
        });
    }
    
    private void createSharedMemory() throws IOException {
        // 创建一块共享内存
        memoryFile = new MemoryFile("shared_memory_demo", BUFFER_SIZE);
        memoryFile.allowPurging(false); // 防止内存被清除
    }
    
    /**
     * 获取MemoryFile的文件描述符
     * 注意：这使用反射，可能在未来版本不再可用
     */
    private ParcelFileDescriptor getFileDescriptor() {
        try {
            Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
            FileDescriptor fd = (FileDescriptor) method.invoke(memoryFile);
            
            return fd != null ? ParcelFileDescriptor.dup(fd) : null;
        } catch (Exception e) {
            Log.e(TAG, "获取文件描述符失败: " + e.getMessage());
            return null;
        }
    }
    
    private void writeToSharedMemory(String content) {
        try {
            byte[] data = content.getBytes(StandardCharsets.UTF_8);
            memoryFile.writeBytes(data, 0, 0, data.length);
            
            updateStatus("数据已写入共享内存: " + content);
            tvMemoryContent.setText(content);
        } catch (IOException e) {
            Log.e(TAG, "写入共享内存错误: " + e.getMessage());
            updateStatus("写入共享内存失败: " + e.getMessage());
        }
    }
    
    private void readFromSharedMemory() {
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead = memoryFile.readBytes(buffer, 0, 0, BUFFER_SIZE);
            
            if (bytesRead > 0) {
                String content = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                tvMemoryContent.setText(content);
                updateStatus("从共享内存读取数据: " + bytesRead + " 字节");
            } else {
                updateStatus("共享内存中没有数据");
            }
        } catch (IOException e) {
            Log.e(TAG, "读取共享内存错误: " + e.getMessage());
            updateStatus("读取共享内存失败: " + e.getMessage());
        }
    }
    
    private void launchRemoteProcess() {
        ParcelFileDescriptor pfd = getFileDescriptor();
        
        if (pfd == null) {
            Toast.makeText(this, "无法获取共享内存文件描述符", Toast.LENGTH_SHORT).show();
            return;
        }
        
        // 启动远程进程并传递文件描述符
        Intent intent = new Intent(this, RemoteProcessActivity.class);
        intent.putExtra(EXTRA_FILE_DESCRIPTOR, pfd);
        intent.putExtra("source", "shared_memory");
        intent.putExtra("message", "这是通过共享内存传递的消息");
        
        try {
            startActivity(intent);
            updateStatus("已启动远程进程");
        } catch (Exception e) {
            Log.e(TAG, "启动远程进程错误: " + e.getMessage());
            updateStatus("启动远程进程失败: " + e.getMessage());
        }
    }
    
    private void updateProcessInfo() {
        String processInfo = "当前进程ID: " + Process.myPid();
        tvStatus.setText(processInfo);
    }
    
    private void updateStatus(String status) {
        String currentStatus = tvStatus.getText().toString();
        tvStatus.setText(currentStatus + "\n" + status);
    }
    
    @Override
    protected void onDestroy() {
        // 关闭共享内存
        if (memoryFile != null) {
            try {
                memoryFile.close();
            } catch (Exception e) {
                Log.e(TAG, "关闭共享内存错误: " + e.getMessage());
            }
        }
        super.onDestroy();
    }
} 